﻿import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:azring/core/repository/default_api.dart';
import 'package:getx_scaffold/common/utils/toast_util.dart';
import 'package:intl/intl.dart';
import 'menstrual_cycle_calendar_state.dart';
import 'widgets/update_period_dialog.dart';

/// 日期状态枚举
enum DayStatus {
  normal,          // 普通日期
  predictedPeriod, // 预测生理期
  period,          // 生理期
  ovulationDay,    // 排卵日
  ovulationPeriod, // 排卵期
}

/// 生理周期日历控制器
class MenstrualCycleCalendarLogic extends GetxController {
  final MenstrualCycleCalendarState state = MenstrualCycleCalendarState();

  @override
  void onInit() {
    super.onInit();
    // 加载当月数据
    initializeCalendar();
    // 加载生理期通知
    loadPeriodNotification();
  }

  @override
  void onReady() {
    super.onReady();
    // 页面准备就绪时也加载数据，确保从其他页面返回时刷新
    loadPhysiologyData();
    loadPeriodNotification();
  }

  /// 初始化日历
  Future<void> initializeCalendar() async {
    // 加载当月生理期数据
    await loadPhysiologyData();
  }

  /// 刷新数据（供外部调用）
  Future<void> refreshData() async {
    // 清空所有缓存数据，重新加载
    state.periodDates.clear();
    state.ovulationDates.clear();
    state.predictedPeriodDates.clear();
    await loadPhysiologyData();
    await loadPeriodNotification();
  }

  /// 加载生理期通知
  Future<void> loadPeriodNotification() async {
    try {
      final result = await DefaultApi().queryAppNoticeInfoGet<Map<String, dynamic>>(
        noticeType: '1', // 1 = 生理期消息
      );

      if (result != null && result['code'] == 200 && result['data'] != null) {
        final data = result['data'];
        final noticeContent = data['noticeContent'] ?? '';
        state.periodNotification.value = noticeContent;
      } else {
        state.periodNotification.value = '';
      }
    } catch (e) {
      print('加载生理期通知失败: $e');
      state.periodNotification.value = '';
    }
  }

  /// 加载生理期数据
  Future<void> loadPhysiologyData() async {
    try {
      state.isLoading.value = true;
      final currentDate = state.currentDate.value;
      final DateFormat formatter = DateFormat('yyyy-MM-dd');
      final selectDate = formatter.format(currentDate);
      
      final result = await DefaultApi().queryPhysiologyInfoGet<Map<String, dynamic>>(
        selectDate: selectDate,
      );

      if (result != null && result['code'] == 200 && result['data'] != null) {
        final data = result['data'];
        
        // 临时存储新数据
        final newPeriodDates = <DateTime>[];
        final newOvulationDates = <DateTime>[];
        final newPredictedPeriodDates = <DateTime>[];

        // 解析生理期日期 (menstrualPeriod: "2025-12-09,2025-12-10,2025-12-11,2025-12-12")
        if (data['menstrualPeriod'] != null && data['menstrualPeriod'].toString().isNotEmpty) {
          final periodDates = data['menstrualPeriod'].toString().split(',');
          for (final dateStr in periodDates) {
            final date = DateTime.tryParse(dateStr.trim());
            if (date != null) {
              newPeriodDates.add(date);
            }
          }
        }

        // 解析排卵期 (ovulationPeriod: "2025-12-18,2025-12-19,2025-12-20,...")
        if (data['ovulationPeriod'] != null && data['ovulationPeriod'].toString().isNotEmpty) {
          final ovulationDates = data['ovulationPeriod'].toString().split(',');
          for (final dateStr in ovulationDates) {
            final date = DateTime.tryParse(dateStr.trim());
            if (date != null) {
              newOvulationDates.add(date);
            }
          }
        }

        // 解析排卵日 (ovulationDay: "2025-12-23")
        // 排卵日用于特殊标记，但也会被包含在排卵期中
        if (data['ovulationDay'] != null && data['ovulationDay'].toString().isNotEmpty) {
          final date = DateTime.tryParse(data['ovulationDay'].toString());
          if (date != null) {
            state.ovulationDate.value = date;
            // 确保排卵日也在排卵期列表中
            if (!newOvulationDates.any((d) => isSameDay(d, date))) {
              newOvulationDates.add(date);
            }
          }
        }

        // 解析预测生理期 (predictMenstrualPeriod: "2026-01-04,2026-01-05,2026-01-06,2026-01-07")
        if (data['predictMenstrualPeriod'] != null && data['predictMenstrualPeriod'].toString().isNotEmpty) {
          final predictDates = data['predictMenstrualPeriod'].toString().split(',');
          for (final dateStr in predictDates) {
            final date = DateTime.tryParse(dateStr.trim());
            if (date != null) {
              newPredictedPeriodDates.add(date);
            }
          }
        }

        // 解析更新的开始日期 (updStartDate: "2025-12-09")
        if (data['updStartDate'] != null) {
          final date = DateTime.tryParse(data['updStartDate'].toString());
          if (date != null) {
            state.lastPeriodDate.value = date;
          }
        }

        // 合并数据：移除旧的相同月份数据，添加新数据
        _mergeMonthData(state.periodDates, newPeriodDates, currentDate);
        _mergeMonthData(state.ovulationDates, newOvulationDates, currentDate);
        _mergeMonthData(state.predictedPeriodDates, newPredictedPeriodDates, currentDate);
      }
    } catch (e) {
      print('加载生理期数据失败: $e');
    } finally {
      state.isLoading.value = false;
    }
  }

  /// 合并月份数据：移除新数据涉及的所有月份的旧数据，添加新数据
  void _mergeMonthData(RxList<DateTime> existingDates, List<DateTime> newDates, DateTime currentMonth) {
    if (newDates.isEmpty) return;
    
    // 找出新数据涉及的所有月份
    final affectedMonths = <String>{};
    for (final date in newDates) {
      affectedMonths.add('${date.year}-${date.month}');
    }
    
    // 移除这些月份的旧数据
    existingDates.removeWhere((date) {
      final monthKey = '${date.year}-${date.month}';
      return affectedMonths.contains(monthKey);
    });
    
    // 添加所有新数据
    existingDates.addAll(newDates);
  }

  /// 从设置页面更新数据
  void updateFromSettings(Map<String, dynamic> settings) {
    // 重新加载数据
    loadPhysiologyData();
  }

  /// 获取当月天数
  int getDaysInMonth() {
    final currentDate = state.currentDate.value;
    final firstDay = DateTime(currentDate.year, currentDate.month, 1);
    final lastDay = DateTime(currentDate.year, currentDate.month + 1, 0);
    
    // 计算第一天是星期几
    final firstWeekday = firstDay.weekday % 7; // 0=Sunday, 1=Monday, etc.
    
    // 计算需要显示的总天数（包括上个月的尾部和下个月的开头）
    final totalDays = lastDay.day + firstWeekday;
    
    // 向上取整到7的倍数
    return ((totalDays / 7).ceil()) * 7;
  }

  /// 获取指定索引的日期
  DateTime getDayForIndex(int index) {
    final currentDate = state.currentDate.value;
    final firstDay = DateTime(currentDate.year, currentDate.month, 1);
    final firstWeekday = firstDay.weekday % 7;
    
    // 计算实际日期
    final dayOffset = index - firstWeekday;
    return firstDay.add(Duration(days: dayOffset));
  }

  /// 获取日期状态
  DayStatus getDayStatus(DateTime date) {
    // 检查是否是生理期
    for (final periodDate in state.periodDates) {
      if (isSameDay(date, periodDate)) {
        return DayStatus.period;
      }
    }
    
    // 检查是否是预测生理期
    for (final predictedDate in state.predictedPeriodDates) {
      if (isSameDay(date, predictedDate)) {
        return DayStatus.predictedPeriod;
      }
    }
    
    // 检查是否是排卵期（包含排卵日）
    for (final ovulationDate in state.ovulationDates) {
      if (isSameDay(date, ovulationDate)) {
        // 如果是当前设置的排卵日，返回排卵日状态
        if (isSameDay(date, state.ovulationDate.value)) {
          return DayStatus.ovulationDay;
        }
        // 否则返回排卵期状态
        return DayStatus.ovulationPeriod;
      }
    }
    
    return DayStatus.normal;
  }

  /// 检查是否是今天
  bool isToday(DateTime date) {
    final today = DateTime.now();
    return isSameDay(date, today);
  }

  /// 检查是否是当前月
  bool isCurrentMonth(DateTime date) {
    final currentDate = state.currentDate.value;
    return date.year == currentDate.year && date.month == currentDate.month;
  }

  /// 检查两个日期是否是同一天
  bool isSameDay(DateTime date1, DateTime date2) {
    return date1.year == date2.year &&
           date1.month == date2.month &&
           date1.day == date2.day;
  }

  /// 上一个月
  void previousMonth() {
    final currentDate = state.currentDate.value;
    state.currentDate.value = DateTime(currentDate.year, currentDate.month - 1, 1);
    // 重新加载数据
    loadPhysiologyData();
  }

  /// 下一个月
  void nextMonth() {
    final currentDate = state.currentDate.value;
    state.currentDate.value = DateTime(currentDate.year, currentDate.month + 1, 1);
    // 重新加载数据
    loadPhysiologyData();
  }

  /// 跳转到今天
  void jumpToToday() {
    final today = DateTime.now();
    state.currentDate.value = DateTime(today.year, today.month, 1);
    // 重新加载数据
    loadPhysiologyData();
  }

  /// 显示更新生理期对话框
  void showUpdatePeriodDialog() {
    state.isEditMode.value = false;
    state.updateStartDate.value = null;
    state.updateEndDate.value = null;
    
    Get.dialog(
      UpdatePeriodDialog(logic: this),
      barrierDismissible: false,
    );
  }

  /// 切换编辑模式
  void toggleEditMode() {
    state.isEditMode.value = !state.isEditMode.value;
  }

  /// 选择开始日期
  Future<void> selectStartDate(BuildContext context) async {
    final DateTime? picked = await showDatePicker(
      context: context,
      initialDate: state.updateStartDate.value ?? DateTime.now(),
      firstDate: DateTime(2020),
      lastDate: DateTime(2030),
      builder: (context, child) {
        return Theme(
          data: ThemeData.dark().copyWith(
            colorScheme: const ColorScheme.dark(
              primary: Color(0xFFFF6B35),
              onPrimary: Colors.white,
              surface: Color(0xFF2A2A2A),
              onSurface: Colors.white,
            ),
          ),
          child: child ?? const SizedBox(),
        );
      },
    );
    
    if (picked != null) {
      state.updateStartDate.value = picked;
      
      // 如果没有选择结束日期，根据设置的生理周期预估
      if (state.updateEndDate.value == null) {
        state.updateEndDate.value = picked.add(Duration(days: state.periodDays.value - 1));
      }
    }
  }

  /// 选择结束日期
  Future<void> selectEndDate(BuildContext context) async {
    final DateTime? picked = await showDatePicker(
      context: context,
      initialDate: state.updateEndDate.value ?? 
                   (state.updateStartDate.value?.add(Duration(days: state.periodDays.value - 1)) ?? DateTime.now()),
      firstDate: state.updateStartDate.value ?? DateTime(2020),
      lastDate: DateTime(2030),
      builder: (context, child) {
        return Theme(
          data: ThemeData.dark().copyWith(
            colorScheme: const ColorScheme.dark(
              primary: Color(0xFFFF6B35),
              onPrimary: Colors.white,
              surface: Color(0xFF2A2A2A),
              onSurface: Colors.white,
            ),
          ),
          child: child ?? const SizedBox(),
        );
      },
    );
    
    if (picked != null) {
      state.updateEndDate.value = picked;
    }
  }

  /// 保存更新的生理期
  Future<void> saveUpdatedPeriod() async {
    final startDateValue = state.updateStartDate.value;
    if (startDateValue == null) {
      Toast.show('请选择开始日期');
      return;
    }

    try {
      final startDate = startDateValue;
      final endDate = state.updateEndDate.value ?? 
                      startDate.add(Duration(days: state.periodDays.value - 1));
      
      final DateFormat formatter = DateFormat('yyyy-MM-dd');
      
      // 1. 生成生理期日期列表（只包含日期的天数，如 "11,12,13,14"）
      final List<String> periodDaysList = [];
      DateTime currentDate = startDate;
      while (currentDate.isBefore(endDate) || currentDate.isAtSameMomentAs(endDate)) {
        periodDaysList.add(currentDate.day.toString().padLeft(2, '0'));
        currentDate = currentDate.add(const Duration(days: 1));
      }
      final menstrualPeriodStr = periodDaysList.join(',');
      
      // 2. 计算排卵日（生理期开始后第14天，通常在周期的中间）
      final ovulationDate = startDate.add(Duration(days: state.cycleDays.value ~/ 2));
      final ovulationDayStr = ovulationDate.day.toString().padLeft(2, '0');
      
      // 3. 计算排卵期（排卵日前4天到后3天，共8天）
      final List<String> ovulationPeriodList = [];
      for (int i = -4; i <= 3; i++) {
        final date = ovulationDate.add(Duration(days: i));
        ovulationPeriodList.add(date.day.toString().padLeft(2, '0'));
      }
      final ovulationPeriodStr = ovulationPeriodList.join(',');
      
      // 4. 计算预测下次生理期（当前生理期开始日期 + 周期天数）
      final nextPeriodStartDate = startDate.add(Duration(days: state.cycleDays.value));
      final List<String> predictPeriodList = [];
      for (int i = 0; i < state.periodDays.value; i++) {
        final date = nextPeriodStartDate.add(Duration(days: i));
        predictPeriodList.add(date.day.toString().padLeft(2, '0'));
      }
      final predictMenstrualPeriodStr = predictPeriodList.join(',');
      
      // 调用API更新生理期
      await DefaultApi().addOrEditPhysiologyPost(
        menstrualPeriod: menstrualPeriodStr,
        ovulationDay: ovulationDayStr,
        ovulationPeriod: ovulationPeriodStr,
        predictMenstrualPeriod: predictMenstrualPeriodStr,
        updStartDate: formatter.format(startDate),
        updEndDate: formatter.format(endDate),
        isShowLoading: true,
      );
      
      // 重新加载数据
      await loadPhysiologyData();
      
      Get.back();
      Toast.show( '生理期已更新');
    } catch (e) {
      Toast.show( '更新失败: $e');
    }
  }
}
